# -*- coding: utf-8 -*-
import os
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext import db

from emof import core as EMOF
from emof import dumper
from emof import loader

from pagesConfiguration import pages

class Model(db.Model):
    model_name = db.StringProperty()
    model_author = db.StringProperty()
    model_comments = db.TextProperty()
    
    model_XMI = db.TextProperty()

class LoadModelStructure(webapp.RequestHandler):
    def get(self):
        def menuClass(clss):
            if clss.package:
                pid = clss.package.id
            else:
                pid = "-1"
                
            menu = "\ntree.add(new dNode({id: '" + clss.id + "',caption: '" + clss.name + "', url: 'javascript:loadClassData(\"" + clss.id + "\");', iconOpen: 'class.gif', iconClosed: 'class.gif'}), '" + pid + "');"
            for att in clss.ownedAttribute:
                menu += "\ntree.add(new dNode({id: '" + att.id + "',caption: '" + att.name + "', url: 'javascript:loadPropertyData(\"" + att.id + "\");', iconOpen: 'property.gif', iconClosed: 'property.gif'}), '" + clss.id + "');"
            for op in clss.ownedOperation:
                menu += menuOperation(op)
            
            return menu
        
        def menuEnumeration(enum):
            if enum.package:
                pid = enum.package.id
            else:
                pid = "-1"

            menu = "\ntree.add(new dNode({id: '" + enum.id + "',caption: '" + enum.name + "', url: 'javascript:loadEnumerationData(\"" + enum.id + "\");', iconOpen: 'enumeration.gif', iconClosed: 'enumeration.gif'}), '" + pid + "');"
            for el in enum.ownedLiteral:
                menu += "\ntree.add(new dNode({id: '" + el.id + "',caption: '" + el.name + "', url: 'javascript:loadEnumerationLiteralData(\"" + el.id + "\");', iconOpen: 'enumliteral.gif', iconClosed: 'enumliteral.gif'}), '" + enum.id + "');"
            
            return menu
        
        def menuPrimitiveType(pt):
            if pt.package:
                pid = pt.package.id
            else:
                pid = "-1"
            
            menu = "\ntree.add(new dNode({id: '" + pt.id + "',caption: '" + pt.name + "', url: 'javascript:loadPrimitiveTypeData(\"" + pt.id + "\");', iconOpen: 'ptype.gif', iconClosed: 'ptype.gif'}), '" + pid + "');"
            
            return menu

        def menuComment(cmm):
            pid = "-1"

            menu = "\ntree.add(new dNode({id: '" + cmm.id + "',caption: '" + cmm._xmi_id + "', url: 'javascript:loadCommentData(\"" + cmm.id + "\");', iconOpen: 'comment.gif', iconClosed: 'comment.gif'}), '" + pid + "');"
            
            return menu

        def menuTag(tag):
            pid = "-1"

            menu = "\ntree.add(new dNode({id: '" + tag.id + "',caption: '" + tag.name + "', url: 'javascript:loadTagData(\"" + tag.id + "\");', iconOpen: 'tag.gif', iconClosed: 'tag.gif'}), '" + pid + "');"
            
            return menu
        
        def menuOperation(op):
            if op.class_:
                pid = op.class_.id
            else:
                pid = "-1"

            menu = "\ntree.add(new dNode({id: '" + op.id + "',caption: '" + op.name + "', url: 'javascript:loadOperationData(\"" + op.id + "\");', iconOpen: 'operation.gif', iconClosed: 'operation.gif'}), '" + pid + "');"
            
            for p in op.ownedParameter:
                menu += "\ntree.add(new dNode({id: '" + p.id + "',caption: '" + p.name + "', url: 'javascript:loadParameterData(\"" + p.id + "\");', iconOpen: 'parameter.gif', iconClosed: 'parameter.gif'}), '" + op.id + "');"
                
            return menu

        def menuPackage(p):
            if p.nestingPackage:
                pid = p.nestingPackage.id
            else:
                pid = "-1"
            
            menu = "\ntree.add(new dNode({id: '" + p.id + "',caption: '" + p.name + "', url: 'javascript:loadPackageData(\"" + p.id + "\");', iconOpen: 'packageopen.gif', iconClosed: 'packageclose.gif'}), '" + pid + "');"
            for t in p.ownedType:
                if isinstance(t, EMOF.Class):
                    menu += menuClass(t)
                elif isinstance(t, EMOF.Enumeration):
                    menu += menuEnumeration(t)
                elif isinstance(t, EMOF.PrimitiveType):
                    menu += menuPrimitiveType(t)
                elif isinstance(t, EMOF.Integer):
                    menu += "\ntree.add(new dNode({id: '" + t.id + "',caption: 'Integer', iconOpen: 'ptype.gif', iconClosed: 'ptype.gif'}), '" + p.id + "');"
                elif isinstance(t, EMOF.String):
                    menu += "\ntree.add(new dNode({id: '" + t.id + "',caption: 'String', iconOpen: 'ptype.gif', iconClosed: 'ptype.gif'}), '" + p.id + "');"
                elif isinstance(t, EMOF.Boolean):
                    menu += "\ntree.add(new dNode({id: '" + t.id + "',caption: 'Boolean', iconOpen: 'ptype.gif', iconClosed: 'ptype.gif'}), '" + p.id + "');"
                elif isinstance(t, EMOF.UnlimitedNatural):
                    menu += "\ntree.add(new dNode({id: '" + t.id + "',caption: 'UnlimitedNatural', iconOpen: 'ptype.gif', iconClosed: 'ptype.gif'}), '" + p.id + "');"

            for t in p.nestedPackage:
                menu += menuPackage(t)
            
            return menu
        
        id = self.request.get("m_id")
        menu = ""
        model = Model.get(id)
        rep = loader.Loader().load(model.model_XMI)
        
        menu = "tree.add(new dNode({id: '-1',caption: '" + model.model_name + "', url: 'javascript:loadModelData();', iconOpen: 'modelopen.gif', iconClosed: 'modelclose.gif'}),-1);"
        
        for p in rep.Package:
            if p.isRoot:
                menu += menuPackage(p)
        for c in rep.Class:
            if c.isRoot:
                menu += menuClass(c)
        for pt in rep.PrimitiveType:
            if pt.isRoot:
                menu += menuPrimitiveType(pt)
        for e in rep.Enumeration:
            if e.isRoot:
                menu += menuEnumeration(e)
        for cmm in rep.Comment:
            menu += menuComment(cmm)
        for tag in rep.Tag:
            menu += menuTag(tag)
        
        template_values = {'model_key': model.key(),
                           'menu': menu}
        
        path = os.path.join(os.getcwd(), 'html/drawModel.html')
        
        p = pages.Pages()
        
        self.response.out.write(p.getHeader(':: Draw metamodels '))
        self.response.out.write(template.render(path, template_values))
        self.response.out.write(p.getFoot(self.request.remote_addr))

class CreateModel(webapp.RequestHandler):
    def get(self):
        model = Model()
        
        rep = EMOF.Repository()
        fact = EMOF.Factory(rep)
        #pkg = fact.create_Package()
        #pkg.name = 'UML - Primitive Types'
        #i = fact.create_Integer()
        #b = fact.create_Boolean()
        #s = fact.create_String()
        #u = fact.create_UnlimitedNatural()
        #pkg.ownedType.append(i)
        #pkg.ownedType.append(b)
        #pkg.ownedType.append(s)
        #pkg.ownedType.append(u)
        
        model.model_XMI = dumper.Dumper().dump(rep)        
        model.model_name = 'New Model'
        model.put()
        
        #template_values = {'model_key': model.key()}
        
        #path = os.path.join(os.getcwd(), 'drawModel.html')
        #self.response.out.write(template.render(path, template_values))
        self.redirect('/model.struct.model?m_id=' + str(model.key()))        

class LoadModelData(webapp.RequestHandler):
    def get(self):
        m_id = self.request.get("m_id")

        model = Model.get(m_id)
        
        #self.response.out.write(os.path.join(os.getcwd(), 'xml/Model.xml'))
        #return
        
        rep = loader.Loader().load(model.model_XMI)
        self.response.headers['Content-Type'] = 'application/xml'
        xml = "<r></r>"
        
        if model:
            template_values = {'id': model.key(),
                               'model': model}
            
            path = os.path.join(os.getcwd(), 'xml/Model.xml')
            xml = template.render(path, template_values)

        self.response.out.write(xml)
 
class SaveModelData(webapp.RequestHandler):
    def post(self):
        m_id = self.request.get("m_id")
        name = self.request.get("name")
        author = self.request.get("author")
        comments = self.request.get("comments")
        
        model = Model.get(m_id)
        
        model.model_name = name
        model.model_author = author
        model.model_comments = comments
        
        model.put()
                
        self.response.out.write("OK")

class ExportModelXMI(webapp.RequestHandler):
    def get(self):
        m_id = self.request.get("m_id")

        model = Model.get(m_id)

        self.response.headers['Content-Type'] = 'application/xml'
        self.response.out.write(model.model_XMI)
        
class ImportModelXMI(webapp.RequestHandler):
    def post(self):
        model = Model()
        model.model_name = self.request.get("name")

        try:
            rep = loader.Loader().load(self.request.POST.get("xmi").file.read())
            model.model_XMI = dumper.Dumper().dump(rep)        
            model.put()
            
            template_values = {'msg': 'Model XMI imported with SUCCESS!'}
        
            path = os.path.join(os.getcwd(), 'html/message.html')
            
            p = pages.Pages()
            
            self.response.out.write(p.getHeader(':: SUCCESS! '))
            self.response.out.write(template.render(path, template_values))
            self.response.out.write(p.getFoot(self.request.remote_addr))
            return
        except:
            template_values = {'msg': 'ERROR on importing the Model XMI!'}
            
            path = os.path.join(os.getcwd(), 'html/message.html')
            
            p = pages.Pages()
            
            self.response.out.write(p.getHeader(':: ERROR! '))
            self.response.out.write(template.render(path, template_values))
            self.response.out.write(p.getFoot(self.request.remote_addr))
        
            return
